package com.ehouse;

import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import com.ehouse.connection.ConnectionManager;

public class SchedulingThread extends Thread {
	
	private final static long TIME_INTERVAL = 60000;
	private final static long CHECK_INTERVAL = 10000;
	private ConnectionManager cm;
	private boolean tempH = true;
	private boolean tempAC = true;
	private boolean irrigation = true;
	private boolean lights = true;
	private int reset = 0;

	public SchedulingThread() {
		super("SchedulingThread");
	}
	
	private void temperatureControl(String rule) {
		double desiredTemp = Double.parseDouble(rule.split("\\\\")[1]);
		double actualTemp = Double.parseDouble(cm.getTemperature()
				.split("/")[1]);

		if (desiredTemp >= actualTemp + 2) {
			cm.switchSensor("Temperature", "AC", false);
			cm.switchSensor("Temperature", "Heating", true);
			if (tempH) {
				try {
					Notifications.getInstance()
					.sendNotifications("Temperature rule triggered. Heating turned ON");
					tempH = false;
					tempAC = true;
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		} else if (desiredTemp <= actualTemp - 2) {
			cm.switchSensor("Temperature", "AC", true);
			cm.switchSensor("Temperature", "Heating", false);
			if (tempAC) {
				try {
					Notifications.getInstance()
					.sendNotifications("Temperature rule triggered. A/C turned ON");
					tempAC = false;
					tempH = true;
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		} else {
			tempAC = true;
			tempH = true;
			cm.switchSensor("Temperature", "AC", false);
			cm.switchSensor("Temperature", "Heating", false);
		}
	}

	@SuppressWarnings("deprecation")
	private void lightControl(List<String> rules) {
		for (String rule : rules) {
			if (!"".equals(rule)) {
				try {
					String[] rule_parts = rule.split("\\\\");
					String time = rule_parts[1];
					SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
					Date df;
					df = sdf.parse(time);
					long now = System.currentTimeMillis();
					Calendar c = Calendar.getInstance();
					c.set(Calendar.HOUR_OF_DAY, df.getHours());
					c.set(Calendar.MINUTE, df.getMinutes());
					c.set(Calendar.SECOND, df.getSeconds());
					long schedule = c.getTimeInMillis();

					if (now + TIME_INTERVAL > schedule
							&& now - TIME_INTERVAL < schedule) {
						System.out.println("Triggered light rule");
						String[] rooms = rule_parts[2].split("/");
						boolean state = "TRUE".equals(rule_parts[3]);
						StringBuffer sb = new StringBuffer();
						if ("TRUE".equals(rooms[1])) {
							cm.switchSensor("Lights", rooms[0], state);
							sb.append(rooms[0]).append(',');
						}
						if ("TRUE".equals(rooms[3])) {
							cm.switchSensor("Lights", rooms[2], state);
							sb.append(rooms[2]).append(',');
						}
						if ("TRUE".equals(rooms[5])) {
							cm.switchSensor("Lights", rooms[4], state);
							sb.append(rooms[4]).append(',');
						}
						if ("TRUE".equals(rooms[7])) {
							cm.switchSensor("Lights", rooms[6], state);
							sb.append(rooms[6]).append(',');
						}

						if (lights) {
							try {
								Notifications.getInstance()
								.sendNotifications("Lights rule triggered. Turning "
								+ (state ? "ON " : "OFF ")
								+ sb.toString().substring(sb.length() - 1));
								lights = false;
							} catch (IOException e) {
								e.printStackTrace();
							}
						}
					}
				} catch (ParseException e) {
					e.printStackTrace();
				}

			}
		}
	}

	@SuppressWarnings("deprecation")
	private void irrigationControl(List<String> rules) {
		for (String rule : rules) {
			if (!"".equals(rule)) {
				try {
					String time = rule.split("\\\\")[1];
					SimpleDateFormat sdf = new SimpleDateFormat("hh:mm");
					Date df;
					df = sdf.parse(time);
					long now = System.currentTimeMillis();
					Calendar c = Calendar.getInstance();
					c.set(Calendar.HOUR_OF_DAY, df.getHours());
					c.set(Calendar.MINUTE, df.getMinutes());
					c.set(Calendar.SECOND, df.getSeconds());
					long schedule = c.getTimeInMillis();
					boolean state = "TRUE".equals(rule.split("\\\\")[2]);

					if (now + TIME_INTERVAL > schedule
							&& now - TIME_INTERVAL < schedule) {
						System.out.println("Triggered irrigation rule");
						cm.switchSensor("Irrigation", "", state);
						if (irrigation) {
							try {
								Notifications.getInstance()
								.sendNotifications("Irrigation rule triggered. Turning irrigation "
										+ (state ? "ON" : "OFF"));
								irrigation = false;
							} catch (IOException e) {
								e.printStackTrace();
							}
						}
					}
				} catch (ParseException e) {
					e.printStackTrace();
				}
			}
		}
	}

	@Override
	public void run() {
		startServer();
		Calendar c = Calendar.getInstance();
		cm.setTime(Integer.toString(c.get(Calendar.YEAR)),Integer.toString(c.get(Calendar.MONTH) + 1),Integer.toString(c.get(Calendar.DAY_OF_MONTH)),Integer.toString(c.get(Calendar.HOUR_OF_DAY)),Integer.toString(c.get(Calendar.MINUTE)),Integer.toString(c.get(Calendar.SECOND)));
		try {
			InetAddress[] all = InetAddress.getAllByName(InetAddress.getLocalHost().getHostName());
			for (InetAddress i : all) {
				String name = NetworkInterface.getByInetAddress(i).getDisplayName().toLowerCase(); 
				if ((name.contains("wireless") || name.contains("wifi")) && !i.getHostAddress().contains(":")) {
					cm.setIp(i.getHostAddress());
					break;
				}
			}
		} catch(Exception e) {
			e.printStackTrace();
		}
		while (true) {
			try {
				List<String> light_rules;
				List<String> irrigation_rules;

				if (!Drivers.getInstance().getLightRules().isEmpty()) {
					light_rules = Drivers.getInstance().getLightRules();
					lightControl(light_rules);
				}

				if (!Drivers.getInstance().getIrrigationRules().isEmpty()) {
					irrigation_rules = Drivers.getInstance()
							.getIrrigationRules();
					irrigationControl(irrigation_rules);
				}

				List<String> tempRules = Drivers.getInstance()
						.getTempRule();
				if (!tempRules.isEmpty()) {
					temperatureControl(tempRules.get(0));
				}
			} catch (IOException ex) {
				ex.printStackTrace();
				startServer();
			} catch (Exception ex) {
				ex.printStackTrace();
			}

			try {
				Thread.sleep(CHECK_INTERVAL);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			reset++;
			if (reset == ((TIME_INTERVAL * 3) / CHECK_INTERVAL)) {
				reset = 0;
				lights = true;
				irrigation = true;
			}
		}

	}

	private void startServer() {
		boolean retry = true;
		while (retry) {
			try {
				cm = new ConnectionManager();
				System.out.println("Connection with board established");
				retry = false;
			} catch (IOException e) {
				System.out.println("Not possible to connect to board. Retrying...");
				e.printStackTrace();
			}
		}
	}
	
}
